package com.sh.data.engine.domain.authority.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sh.data.engine.domain.authority.model.domain.MenuDomain;
import com.sh.data.engine.domain.authority.model.domain.RoleDomain;
import com.sh.data.engine.domain.authority.model.mapper.MenuDomainMapper;
import com.sh.data.engine.domain.authority.service.MenuService;
import com.sh.data.engine.domain.authority.service.RoleMenuService;
import com.sh.data.engine.domain.authority.service.RoleService;
import com.sh.data.engine.domain.workspace.manager.model.domain.UserDomain;
import com.sh.data.engine.domain.workspace.manager.service.UserService;
import com.sh.data.engine.repository.dao.authority.MenuMapper;
import com.sh.data.engine.repository.dao.authority.entity.MenuEntity;
import com.sh.data.engine.repository.dao.authority.entity.RoleEntity;
import com.sh.data.engine.repository.dao.authority.entity.RoleMenuEntity;
import com.sh.data.engine.repository.dao.base.EngineBaseModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @author tinglan.ys @Title: @Package: @Description:
 * @date 2022/1/5 下午3:59
 */
@Service
@Slf4j
public class MenuServiceImpl extends ServiceImpl<MenuMapper, MenuEntity> implements MenuService {

    @Lazy
    @Autowired
    private UserService userService;

    @Lazy
    @Autowired
    private RoleService roleService;

    @Lazy
    @Autowired
    private RoleMenuService roleMenuService;

    private static transient Logger logger = LoggerFactory.getLogger(MenuServiceImpl.class);

    @Autowired
    private MenuDomainMapper menuDomainMapper;

    @Override
    public List<MenuDomain> menuList() {

        String belong = "1";

        // 2022.6.1 新增逻辑 角色配置那里的菜单列表 不展示管理中心和个人中心菜单、授权审批和安全管理
        // 也就是说管理员无法给角色赋予上述菜单权限
//        List<Long> childId = getChildId(MenuEnumNew.GLZX.getId());
//        childId.add(MenuEnumNew.GRZX.getId());
        // 2022.8.15 新增逻辑 又需要展示授权审批和//安全管理
//        if (!"1".equals("0")) {
//            //开启3员的话，授权审批需要展示
//            childId.add(MenuEnumNew.SQSP.getId());
//        }
//        childId.add(MenuEnumNew.AQGL.getId());

        List<MenuEntity> menuEntityList = new ArrayList<>();
        // 敏捷版菜单
        menuEntityList =
            this.list(
                new LambdaQueryWrapper<MenuEntity>()
//                    .notIn(MenuEntity::getId, childId)
                    .ne(MenuEntity::getBelong, "2"));

        return menuDomainMapper.map(menuEntityList);
    }

    private List<Long> getChildId(Long pId) {
        // 获取某个菜单的所有子id，包含自己的id返回 一共就3级目录，就不递归了
        List<Long> menuId = new ArrayList<>();
        menuId.add(pId);

        final List<MenuEntity> menuEntityList =
            this.list(new LambdaQueryWrapper<MenuEntity>().eq(MenuEntity::getParentId, pId));

        if (CollectionUtils.isNotEmpty(menuEntityList)) {
            // 有子
            for (MenuEntity menuEntity : menuEntityList) {
                menuId.add(menuEntity.getId());

                List<MenuEntity> menuEntityList2 =
                    this.list(
                        new LambdaQueryWrapper<MenuEntity>()
                            .eq(MenuEntity::getParentId, menuEntity.getId()));

                if (CollectionUtils.isNotEmpty(menuEntityList)) {
                    // 还有子
                    for (MenuEntity entity : menuEntityList2) {
                        menuId.add(entity.getId());
                    }
                }
            }
        }
        return menuId;
    }

    @Override
    public MenuDomain getMenusById(Long id) {
        MenuEntity menuEntity = this.getById(id);
        if (menuEntity == null) {
            logger.error("id为" + id + "的菜单不存在");
            return null;
        } else {
            MenuDomain menuDomain = menuDomainMapper.map(menuEntity);
            if (StringUtils.isNotBlank(menuEntity.getApiIds())) {
                String[] strArr = menuEntity.getApiIds().split(",");
                List<Long> apiIds = Arrays.stream(strArr).map(Long::valueOf).collect(toList());
                menuDomain.setApiIds(apiIds);
            }
            return menuDomain;
        }
    }

    @Override
    public List<RoleDomain.SimpleMenuEntity> getMenusId(String userId) {
        // 查询该用户拥有的菜单列表Id
        UserDomain userDomain = userService.getUserById(userId);
        if (userDomain == null) {
            logger.warn("无法找到userId为" + userId + "的用户");
            return null;
        }

        if (userDomain.getRoleId() == 0) {
            logger.warn("未给" + userDomain.getUserName() + "用户分配角色");
            return null;
        }

        final RoleEntity roleEntity = roleService.getById(userDomain.getRoleId());
        if (roleEntity == null) {
            logger.warn("无法找到roleId为" + userId + "的角色");
            return null;
        }

        // 如果是系统超级管理员角色，那么拥有所有的菜单且权限为读写
        if (userDomain.getRoleId() == 1) {
            List<MenuEntity> all =
                this.list(
                    new LambdaQueryWrapper<MenuEntity>()
                        .orderByAsc(MenuEntity::getId));
            List<RoleDomain.SimpleMenuEntity> menuList = new ArrayList<>();
            for (MenuEntity menuEntity : all) {
                RoleDomain.SimpleMenuEntity menu = new RoleDomain.SimpleMenuEntity();
                menu.setMenuId(menuEntity.getId());
                menu.setReadWriteStatus(1);
                menuList.add(menu);
            }
            return menuList;
        }

        final List<RoleMenuEntity> roleMenuEntityList =
            roleMenuService.list(
                new LambdaQueryWrapper<RoleMenuEntity>()
                    .eq(RoleMenuEntity::getRoleId, userDomain.getRoleId()));

        List<RoleDomain.SimpleMenuEntity> menuList =
            roleMenuEntityList.stream()
                .map(
                    rm -> {
                        RoleDomain.SimpleMenuEntity menu = new RoleDomain.SimpleMenuEntity();
                        menu.setMenuId(rm.getMenuId());
                        menu.setReadWriteStatus(rm.getReadWriteStatus());
                        return menu;
                    })
                .collect(toList());
        return menuList;
    }

    @Override
    public List<RoleDomain.SimpleMenuEntity> getMenusByRoleId(Long roleId) {

        final RoleEntity roleEntity = roleService.getById(roleId);
        if (roleEntity == null) {
            // logger.error("无法找到roleId为" + userId + "的角色");
            return null;
        }

        // 如果是系统管理员角色，那么拥有所有的菜单 且权限为读写
        if (roleEntity.getIsSystem() == 1) {
            List<MenuEntity> all = this.list();
            List<RoleDomain.SimpleMenuEntity> menuList = new ArrayList<>();
            for (MenuEntity menuEntity : all) {
                RoleDomain.SimpleMenuEntity menu = new RoleDomain.SimpleMenuEntity();
                menu.setMenuId(menuEntity.getId());
                menu.setReadWriteStatus(1);
                menuList.add(menu);
            }

            return menuList;
        }

        final List<RoleMenuEntity> roleMenuEntityList =
            roleMenuService.list(
                new LambdaQueryWrapper<RoleMenuEntity>().eq(RoleMenuEntity::getRoleId, roleId));

        return roleMenuEntityList.stream()
            .map(
                rm -> {
                    RoleDomain.SimpleMenuEntity menu = new RoleDomain.SimpleMenuEntity();
                    menu.setMenuId(rm.getMenuId());
                    menu.setReadWriteStatus(rm.getReadWriteStatus());
                    return menu;
                })
            .collect(Collectors.toList());
    }

    @Override
    public String listId() {
        List<MenuEntity> all = this.list();

        List<Long> collect = all.stream().map(EngineBaseModel::getId).collect(Collectors.toList());

        return StringUtils.join(collect, ",");
    }

    @Override
    public Map<Long, String> getMenuMapByIds(List<Long> ids) {
        final List<MenuEntity> multi = this.listByIds(ids);
        return multi.stream()
            .collect(Collectors.toMap(MenuEntity::getId, MenuEntity::getMenuName, (k1, k2) -> k1));
    }
}
